1 module hip.game2d.threepatch;
2 
3 public import hip.api.renderer.texture;
4 public import hip.game2d.sprite;
5 import hip.api;
6 import hip.game2d.renderer_data;
7 
8 enum ThreePatchOrientation
9 {
10     horizontal,
11     vertical,
12     inferred
13 }
14 
15 
16 class ThreePatch
17 {
18     int x, y;
19     int width, height;
20     HipSpriteVertex[4*3] vertices;
21     HipSprite[3] sprites;
22     ThreePatchOrientation orientation;
23     ThreePatchOrientation inferredOrientation = ThreePatchOrientation.inferred;
24 
25     this(string texturePath, ThreePatchOrientation orientation = ThreePatchOrientation.inferred)
26     {
27         this(HipAssetManager.loadTexture(texturePath).awaitAs!IHipTexture, width, height, orientation);
28     }
29     this(IHipTexture texture, int width, int height, ThreePatchOrientation orientation = ThreePatchOrientation.inferred)
30     {
31         for(int i = 0; i < 3; i++)
32             sprites[i] = new HipSprite(texture);
33 
34         this.orientation = orientation;
35         this.inferredOrientation = infer(width, height);
36         setSize(width, height);
37     }
38     pragma(inline) ThreePatchOrientation getOrientation()
39     {
40         if(orientation == ThreePatchOrientation.inferred)
41             return inferredOrientation;
42         return orientation;
43     }
44     void setOrientation(ThreePatchOrientation ori = ThreePatchOrientation.horizontal)
45     {
46         if(orientation == ThreePatchOrientation.inferred)
47             return setOrientation(inferredOrientation);
48         if(ori != orientation)
49         {
50             orientation = ori;
51             build();
52         }
53     }
54 
55     void setSize(int width, int height)
56     {
57         this.width = width;
58         this.height = height;
59 
60         
61         if(getOrientation == ThreePatchOrientation.horizontal)
62         {
63             float rw = sprites[0].getTextureWidth/3;
64             sprites[0].setRegion(0, 0, rw, 1.0);
65             sprites[1].setRegion(rw, 0, rw*2, 1.0);
66             sprites[2].setRegion(rw*2, 0, rw*3, 1.0);
67         }
68         else
69         {
70             float rh = sprites[0].getTextureHeight/3;
71             sprites[0].setRegion(0, 0, rh, 1.0);
72             sprites[1].setRegion(rh, 0, rh*2, 1.0);
73             sprites[2].setRegion(rh*2, 0, rh*3, 1.0);
74         }
75         build();
76     }
77 
78     protected void updatePosition()
79     {
80         if(getOrientation == ThreePatchOrientation.horizontal)
81         {
82             int spWidth = sprites[0].width;
83             sprites[0].setPosition(x, y);
84             sprites[1].setPosition(x+spWidth, y);
85             sprites[2].setPosition(x+width-(spWidth*2), y);
86         }
87         else
88         {
89             int spHeight = sprites[0].height;
90             sprites[0].setPosition(x, y);
91             sprites[1].setPosition(x, y+spHeight);
92             sprites[2].setPosition(x, y+height-(spHeight*2));
93         }
94     }
95 
96     void build()
97     {
98         if(getOrientation == ThreePatchOrientation.horizontal)
99         {
100             int spWidth = sprites[0].width;
101             float xScalingFactor = width-(spWidth*2);
102             if(spWidth != 0)
103                 xScalingFactor/= spWidth;
104             else
105                 xScalingFactor = 0;
106 
107             sprites[0].setPosition(x, y);
108             sprites[1].setPosition(x+spWidth, y);
109             sprites[1].setScale(xScalingFactor, 1);
110             sprites[2].setPosition(x+width-(spWidth*2), y);
111         }
112         else
113         {
114             int spHeight = sprites[0].height;
115             float yScalingFactor = height-(spHeight*2);
116             if(spHeight != 0)
117                 yScalingFactor/= spHeight;
118             else
119                 yScalingFactor = 0;
120 
121             sprites[0].setPosition(x, y);
122             sprites[1].setPosition(x, y+spHeight);
123             sprites[1].setScale(1, yScalingFactor);
124             sprites[2].setPosition(x, y+height-(spHeight*2));
125         }
126     }
127 
128     
129 
130     void setPosition(int x, int y)
131     {
132         updatePosition();
133     }
134 
135     ref HipSpriteVertex[4*3] getVertices(){return vertices;}
136 
137 }
138 
139 private ThreePatchOrientation infer(int width, int height){return width > height ? ThreePatchOrientation.horizontal : ThreePatchOrientation.vertical;}
140 
141 
142 /**
143 *     0  1  2 
144 *    ________
145 *   |________|
146 *
147 *
148 *    ___
149 *   |   | 0
150 *   |   | 1
151 *   |___| 2
152 */